package com.ludomancy.breathe;

import java.util.Iterator;
import java.util.Vector;

import com.ludomancy.gamelib.Randomizer;

public class Game
{
	public static Game game;
	
	public Vector options = new Vector();
	private String mainText;
	
	public int anxiety = 0;
	public boolean freeHand = false;
	public int struggleCount = 0;
	public boolean finalSequence = false;
	public boolean windowBlocked = false;
	
	public static final int TREE = 1;
	public static final int DESK = 2;
	public static final int RUG = 3;
	public static final int BALCONY = 4;
	public static final int WINDOW = 5;
	public static final int roomSize = WINDOW+1;
	public int position;
//	public static final String[] descriptions = new String[]{"","","You're on the rug.","","The air is colder here."};
	
	public Vector objects = new Vector();
	public Fire fire;
	public Couch couch;
	public Cat cat;
	public Tree tree;
	public TV tv;
	
	// options
	public static Option start = new Option("Put on Sweater");
	public static Option struggle = new Option("Struggle");
	public static Option breathe = new Option("Breathe");
	public static Option restart = new Option("Restart");
	public static Option push = new Option("Push Couch");
	public static Option turnOffTV = new Option("Turn Off TV");
	public static final Option win = new Option("Pass out");
	public static final Option moveTree = new Option("Throw Tree");
	
	// moods
	public static final int MOOD_DESPERATE = 5;
	public static final int MOOD_OUTOFCONTROL = 8;
	
	// states
	public static final int STATE_INTRO = 1;
	public static final int STATE_GAME = 2;
	public static final int STATE_DEATH = 3;
	public static final int STATE_WIN = 4;

	// struggle desc
	public static final String[] struggleDesc = new String[]
   {
		"You push hard with your left and twist around.",
		"You wonder if you shoved your head in the sleeve intead of the neck. You try to pull you head out, but the sweater only gets tighter.",
		"You jump and bend but it's like being in a shut down jaw.",
		"Lifting your shoulders doesn't help either but to get your forehead smashed into a wall.",
		"You shake furiously and you almost get free. But then the sweater swallows again.",
   };
	public int struggleDescIndex = 0;

	public static final String[] struggleDescFreeHand = new String[]
   {
		"You try to get the right hand to release the left, but you can't move it that far.",
		"You turn around but the right hand only waves randomly.",
		"The right hand only manages to scratch you until it hurts.",
		"The right hand moves on itself now, and you can only move around trying to avoid it.",
   };
	public int struggleDescFreeHandIndex = 0;

	public static final String[] breatheDesc = new String[]
   {
		"You take a deep breath and think.",
		"You calm yourself down.",
		"You recover yourself a bit.",
		"You remember that the window is open and stop twisting for a moment.",
		"You stop for a moment.",
   };
	public int breatheIndex = 0;

	public int state = STATE_INTRO;
	
	public Game()
	{
		game = this;

		// add the interactables
		cat = new Cat();
		couch = new Couch(Game.RUG);
		tree = new Tree(Game.DESK);
		fire = new Fire();
		tv = new TV();
		objects.add(cat);
		objects.add(couch);
		objects.add(tree);
		objects.add(fire);
		objects.add(tv);
		
		state = STATE_INTRO;
		mainText = "You are going to be late. So you hurry up to look at your suit in the mirror and realize it's cold and decide to put on that old blue sweater that is the only thing that will look acceptable. You take a look at the christmas tree and can't help thinking it's only there to comply with some rule.";
		mainText += "\nThe cat wakes up from the nap in your couch.";
		mainText += "\nYou leave your cigarette on the ashtray over the TV and walk up to the mirror.";
		options.add(start);
		position = Game.DESK;
	}
	
	public int getValidRandomLocation(int otherThan)
	{
		int newPos = Randomizer.getRandom(1,roomSize-1);
		while(newPos == otherThan)
		{
			newPos = Randomizer.getRandom(1,roomSize-1);
		}
		return newPos;
	}
	
	public boolean isCalm()
	{
		return anxiety < MOOD_DESPERATE;
	}
	
	public boolean isDesperate()
	{
		return anxiety >= MOOD_DESPERATE && anxiety < MOOD_OUTOFCONTROL;
	}
	
	public boolean isOutOfControl()
	{
		return anxiety == MOOD_OUTOFCONTROL;
	}
	
	public void increaseAnxiety()
	{
		boolean wasDesperate = isDesperate();
		boolean wasOutOfControl = isOutOfControl();
		anxiety++;
		anxiety = Math.min(MOOD_OUTOFCONTROL, anxiety);
		if(isDesperate() && !wasDesperate)
		{
			addResponse("You're getting desperate.");
		}
		if(isOutOfControl() && !wasOutOfControl)
		{
			addResponse("You completely lose control.");
		}
	}
	
	public String getMainText()
	{
		return mainText;
	}
	
	public void update()
	{
	}
	
	public boolean hasOption(Option option)
	{
		for (Iterator iter = options.iterator(); iter.hasNext();)
		{
			Option opt = (Option) iter.next();
			if(opt.label.equals(option.label))
			{
				return true;
			}
		}
		return false;
	}
	
	public void addOption(Option option)
	{
		if(!hasOption(option))
		{
			options.add(option);
		}
	}
	
	public void removeOption(Option option)
	{
		for (Iterator iter = options.iterator(); iter.hasNext();)
		{
			Option opt = (Option) iter.next();
			if(opt.label.equals(option.label))
			{
				options.remove(opt);
				break;
			}
		}
	}
	
	public void addResponse(String resp)
	{
		if(resp != null && resp.length() > 0)
		{
			mainText += resp + "\n";
		}
	}

	public void chooseOption(Option option)
	{
		if(option == restart)
		{
			BreatheApp.app.resetGame();
		}
		else
		{
			options.clear();
			mainText = "";
			processOption(option);
			if(state != STATE_DEATH && state != STATE_WIN)
			{
				// first, special tile descriptions
				if(position == Game.RUG)
				{
					if(fire.isFiring())
					{
						addResponse("You are on the burning rug. The heat is unbearable.");
					}
					else
					if(fire.isSmoking())
					{
						addResponse("You are on the rug. The smell of smoke mixed with lint is strangling.");
					}
					else
					{
						addResponse("You feel the rug with your feet.");
					}
				}
				else
				if(position == WINDOW)
				{
					addResponse("Window is close. Air is colder.");
				}
				
				// output the entities
				cat.doTurn();
				fire.doTurn();
				tree.doTurn();
				couch.doTurn();
				if(!finalSequence)
				{
					// output state of mind
					if(isDesperate())
					{
						addResponse("You are losing control.");
					}
					else
					if(isOutOfControl())
					{
						addResponse("Your body moves by itself. Can't stop mumbling to yourself.");
					}
				}
			}
//			mainText +="\npos: "+position+ " anx: "+anxiety+ "cat "+cat.position;
			BreatheApp.mainWidget.options.changeOptions(options);
		}
	}
	
	void move()
	{
		position = getValidRandomLocation(position);
		Vector objs = getObjectsIn(position);
		for (Iterator iter = objs.iterator(); iter.hasNext();)
		{
			RoomObject obj = (RoomObject) iter.next();
			obj.onBump();
		}
	}
	
	public Vector getObjectsIn(int p)
	{
		Vector ret = new Vector();
		for (Iterator iter = objects.iterator(); iter.hasNext();)
		{
			RoomObject obj = (RoomObject) iter.next();
			if(obj.position == p)
			{
				ret.add(obj);
			}
		}
		return ret;
	}
	
	private void processOption(Option option)
	{
		if(option == win)
		{
			state = STATE_WIN;
			addResponse("You hear a breathing in your face and your head hurts and your eyes sting so you open them. It's the cat again. You stand, straighten you suit and lift the tree. All seems to be fine. Except for the small burn in the rug's corner - she's going to be pissed and you're late. You hurry up and grab the jacket. You can't find the sweater anywhere.");
			addResponse("\n\n\nYou Win! Thanks for playing - Daniel Benmergui");
			return;
		}
		if(option == start)
		{
			state = STATE_GAME;
			Game.game.addResponse("The wool of the sweater glues itself to the shirt. It's not easy and you try to force the left hand but it doesn't come out. So you attempt putting both hands at the same time but it doesn't work and your head doesn't help so you try to force both hands and the head at the same time, but nothing moves.");
			Game.game.addResponse("You try to take the sweater and start again. But the wool is strangling both your hands and your neck. You mouth is getting full of lint and it tastes like mothballs. Every move you make hurts. You can't see a thing.");
			Game.game.addResponse("You're stuck in your sweater.");
		}
		else
		if(option == struggle)
		{
			// special case close to the window
			if(position == WINDOW)
			{
				if(isOutOfControl())
				{
					if(windowBlocked)
					{
						addResponse("While desperate, you trip with the couch and fall forward...");
					}
					// bye
					die();
					return;
				}
				else
				if(isDesperate())
				{
					if(windowBlocked)
					{
						// the couch just saved me
						addResponse("You carelessly step forward and bounce against your couch. If it wasn't there you could have fallen off the window.");
						move();
					}
					else
					{
						// bye
						die();
						return;
					}
				}
				else
				{
					// do not jump out of the window!
					Game.game.addResponse("You remember the window is close. You move away.");
					move();
				}
			}
			else
			{
				struggle();
				move();
			}
			Game.game.increaseAnxiety();
		}
		else
		if(option == breathe)
		{
			breathe();
		}
				
		// give interactables a chance to react to this command
		for (Iterator iter = objects.iterator(); iter.hasNext();)
		{
			RoomObject obj = (RoomObject) iter.next();
			obj.processOption(option);
		}
		// add default options
		Game.game.addOption(struggle);
		if(anxiety > 0)
		{
			Game.game.addOption(breathe);
		}

	}

	public void die()
	{
		addResponse("You are finally free. You stop struggling and feel the cold wind hitting your face and all else goes away and twelve stories down.");
		addResponse("\n\nHints(spoilers):\nYou'll need to get out of control, but do not go overboard, specially close to the window. Try to go back and forth with struggling and breathing. Try to struggle while being blue.");
		state = STATE_DEATH;
		options.clear();
		options.add(restart);
	}
	
	private void breathe()
	{
		if(fire.isSmoking() && anxiety <= MOOD_DESPERATE)
		{
			addResponse("You take a deep breath but the acrid smell of the fire makes you cough. You think about how you could die choked on the smoke, and it makes the blue wool feel more strangling. You cannot relax.");
			anxiety = MOOD_DESPERATE;
		}
		else
		{
			if(anxiety == 0)
			{
				Game.game.addResponse("You hyperventilate and get dizzy.");
			}
			else
			{
				anxiety--;
				anxiety = Math.max(0, anxiety);
				if(anxiety == MOOD_DESPERATE-1)
				{
					addResponse("You calm yourself and start thinking clearly again.");
				}
				else
				if(anxiety == MOOD_OUTOFCONTROL-1)
				{
					addResponse("You feel you're getting a grip on yourself.");
				}
				else
				{
					breatheIndex = breatheIndex % breatheDesc.length;
					Game.game.addResponse(breatheDesc[breatheIndex++]);
				}
			}
		}
	}

	public void struggle()
	{
		if(isCalm())
		{
			struggleCount++;
		}
		if(struggleCount == 5)
		{
			addResponse("You try a different approach, by wiggling your right hand and your head at the same time. After a while, you feel the fresh air in your right hand. For a moment you think this is over, but then you realize that you can't move it much.");
			addResponse("At least your right hand is partially free!");
			freeHand = true;
		}
		else
		{
			if(freeHand)
			{
				struggleDescFreeHandIndex = struggleDescFreeHandIndex % struggleDescFreeHand.length;
				addResponse(struggleDescFreeHand[struggleDescFreeHandIndex++]);
			}
			else
			{
				struggleDescIndex = struggleDescIndex % struggleDesc.length;
				addResponse(struggleDesc[struggleDescIndex++]);//"You push with your left hand to set it free, but you only manage to push it very little. You twist and turn and it doesn't make a difference. You lost your orientation.");
			}
		}
	}

}
